import { Inject, Provide } from '@midwayjs/decorator';
import { InjectEntityModel } from '@midwayjs/orm';
import { QueryRunner, Repository } from 'typeorm';
import { ICoolCache, Cache, CoolTransaction } from 'midwayjs-cool-core';

import { CreateProductDto, UpdateProductDto } from '../dto/product';
import { BasePageDto } from '../dto/base';

import { MallProductEntity } from '../entity/product';
import { MallProductClothingEntity } from '../entity/productClothing';

@Provide()
export class MallProductService {
  @InjectEntityModel(MallProductEntity)
  mallProductEntity: Repository<MallProductEntity>;

  @InjectEntityModel(MallProductClothingEntity)
  mallProductClothingEntity: Repository<MallProductClothingEntity>;

  @Inject('cool:cache')
  coolCache: ICoolCache;

  // 增
  async add(product: CreateProductDto) {
    return await this.mallProductEntity.save(product);
  }

  // 删
  @CoolTransaction({ isolation: 'SERIALIZABLE' })
  async delete(productId: number, queryRunner?: QueryRunner) {
    // 事务：同时删除 productClothing 中的 SKU 信息
    await queryRunner.manager.delete<MallProductClothingEntity>(
      MallProductClothingEntity,
      { productId }
    );
    await queryRunner.manager.delete<MallProductEntity>(MallProductEntity, {
      id: productId,
    });
  }

  // 改
  async update(product: UpdateProductDto) {
    try {
      await this.mallProductEntity.update(product.id, product);
      return await this.mallProductEntity.findOne(product.id);
    } catch (err) {
      return new Error(err.message);
    }
  }

  // 查
  async info(productId: number) {
    return await this.mallProductEntity.findOne({ id: productId });
  }

  // 分页
  @Cache(5)
  async page(op: BasePageDto) {
    const count = await this.mallProductEntity.count();
    const data = await this.mallProductEntity
      .createQueryBuilder('p')
      .select([
        'p.id',
        'p.title',
        'p.poster',
        'p.sale',
        'p.categoryId',
        'p.keyword',
        'p.carousel',
        'p.detail',
      ])
      .skip(op.start)
      .take(op.limit)
      .orderBy('p.id', op.order)
      .getMany();
    return { data, count };
  }
}
